package com.mall.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.mall.dao.OrderItemMapper;
import com.mall.dao.OrderMapper;
import com.mall.dao.ProductMapper;
import com.mall.dao.ShippingMapper;
import com.mall.enums.ProductStatusEnum;
import com.mall.enums.ResponseEnum;
import com.mall.enums.OrderStatusEnum;
import com.mall.enums.PaymentTypeEnum;
import com.mall.pojo.*;
import com.mall.service.ICartService;
import com.mall.service.IOrderService;
import com.mall.vo.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author: 黄建
 * @Date: 2020/1/26 22:32
 */
@Service
public class OrderServiceImpl implements IOrderService {

    private final static String CART_REDIS_KEY_TEMPLATE = "cart_%d";


    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private ICartService cartService;

    @Autowired
    private ShippingMapper shippingMapper;

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private OrderItemMapper orderItemMapper;

    @Autowired
    private ProductMapper productMapper;


    public ResponseVo<OrderVo> create1(Integer uid, Integer shippingId) {
        HashOperations<String, String, String> opsForHash = redisTemplate.opsForHash();
        String redisKey = String.format(CART_REDIS_KEY_TEMPLATE, uid);


        Order order = new Order();

        Long orderNo = 1111L;

        //收货地址校验
        Shipping shipping = shippingMapper.selectByUserIdShippingId(uid, shippingId);
        if (shipping == null) {
            return ResponseVo.error(ResponseEnum.SHIPPING_NOT_EXIST);
        }

        //获取购物车，校验商品、库存
        CartVo cartVo = cartService.list(uid).getData();

        List<CartProductVo> cartProductVoList = cartVo.getCartProductVoList();

        List<OrderItem> orderItems = new ArrayList<>();

        BigDecimal payment = BigDecimal.ZERO;

        for (CartProductVo cartProductVo :
                cartProductVoList) {
            if (cartProductVo.getProductStatus().equals(ProductStatusEnum.ON_SALE.getCode()) && cartProductVo.getProductStock() >= cartProductVo.getQuantity()) {
                OrderItem orderItem = new OrderItem();
                orderItem.setOrderNo(orderNo);
                orderItem.setUserId(uid);
                orderItem.setProductId(cartProductVo.getProductId());
                orderItem.setProductName(cartProductVo.getProductName());
                orderItem.setProductImage(cartProductVo.getProductMainImage());
                orderItem.setCurrentUnitPrice(cartProductVo.getProductPrice());
                orderItem.setQuantity(cartProductVo.getQuantity());
                orderItem.setTotalPrice(cartProductVo.getProductTotalPrice());
                //计算总价格，计算被选中的商品
                orderItems.add(orderItem);

                int updateStock = productMapper.updateStock(cartProductVo.getProductId(), cartProductVo.getProductStock() - cartProductVo.getQuantity());

                if (updateStock <= 0) {
                    return ResponseVo.error(ResponseEnum.PRODUCT_STOCK_ERROR);
                }

                //减库存
                payment = payment.add(cartProductVo.getProductTotalPrice());

                //更新购物车 删掉选中的商品
                opsForHash.delete(redisKey, String.valueOf(cartProductVo.getProductId()));
            }
        }
        if (orderItems.size() == 0) {
            return ResponseVo.error(ResponseEnum.CART_SELECTED_IS_EMPTY);
        }
        order.setOrderNo(orderNo);
        order.setPayment(payment);
        order.setPaymentType(PaymentTypeEnum.PAY_ONLINE.getCode());
        order.setPostage(0);
        order.setStatus(OrderStatusEnum.NO_PAY.getCode());
        order.setCreateTime(new Date());
        order.setUserId(uid);
        order.setShippingId(shippingId);

        //生成订单，入库
        orderMapper.insertSelective(order);
        orderItemMapper.insertOrderItems(orderItems);


        //构造orderVo
        OrderVo orderVo = buildOrderVo(order, orderItems, shipping);

        return ResponseVo.success(orderVo);
    }


    @Override
    @Transactional
    public ResponseVo<OrderVo> create(Integer uid, Integer shippingId) {


        //收货地址校验
        Shipping shipping = shippingMapper.selectByUserIdShippingId(uid, shippingId);
        if (shipping == null) {
            return ResponseVo.error(ResponseEnum.SHIPPING_NOT_EXIST);
        }

        //获取购物车，校验商品、库存
        List<Cart> carts = cartService.listForCart(uid).stream().filter(Cart::getProductSelected).collect(Collectors.toList());

        if (CollectionUtils.isEmpty(carts)){
            return ResponseVo.error(ResponseEnum.PRODUCT_NOT_EXIST);
        }

        List<OrderItem> orderItems = new ArrayList<>();
        BigDecimal payment = BigDecimal.ZERO;

        //查出最新状态商品信息
        Set<Integer> productIds = carts.stream().map(Cart::getProductId).collect(Collectors.toSet());
        System.out.println(productIds);
        List<Product> products = productMapper.selectByProductIdSet(productIds);
        Map<Integer, Product> map = products.stream().collect(Collectors.toMap(Product::getId, product -> product));

        Long orderNo = generateOrderNo();

        for (Cart cart : carts) {
            Product product = map.get(cart.getProductId());

            //是否有商品
            if (product == null) {
                return ResponseVo.error(ResponseEnum.PRODUCT_NOT_EXIST,
                        "商品不存在. productId = " + cart.getProductId());
            }
            //商品上下架状态
            if (!ProductStatusEnum.ON_SALE.getCode().equals(product.getStatus())) {
                return ResponseVo.error(ResponseEnum.PRODUCT_OFF_SALE_OR_DELETE,
                        "商品不是在售状态. " + product.getName());
            }

            //库存是否充足
            if (product.getStock() < cart.getQuantity()) {
                return ResponseVo.error(ResponseEnum.PRODUCT_STOCK_ERROR,
                        "库存不正确. " + product.getName());
            }

            //减库存
            int updateStock = productMapper.updateByPrimaryKeySelective(product);

            if (updateStock <= 0) {
                return ResponseVo.error(ResponseEnum.PRODUCT_STOCK_ERROR);
            }

            OrderItem orderItem = buildOrderItem(uid, orderNo, cart.getQuantity(), product);
            orderItems.add(orderItem);
        }

        //生成订单，入库
        Order order = buildOrder(orderNo, uid, orderItems, shippingId);

        int insertSelective = orderMapper.insertSelective(order);

        if (insertSelective <= 0) {
            return ResponseVo.error(ResponseEnum.ERROR);
        }

        int insertOrderItems = orderItemMapper.insertOrderItems(orderItems);
        if (insertOrderItems <= 0) {
            return ResponseVo.error(ResponseEnum.ERROR);
        }

        //删除购物车中的数据
        for (OrderItem orderItem : orderItems) {
            cartService.delete(uid, orderItem.getProductId());
        }

        //构造orderVo
        OrderVo orderVo = buildOrderVo(order, orderItems, shipping);

        return ResponseVo.success(orderVo);
    }


    @Override
    public ResponseVo<PageInfo<OrderVo>> list(Integer uid, Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum, pageSize);

        List<OrderVo> orderVos = new ArrayList<>();

        List<Order> orders = orderMapper.selectByUserId(uid);

        //获取所有订单编号
        Set<Long> orderNoSet = orders.stream().map(Order::getOrderNo).collect(Collectors.toSet());

        //获取所有订单编号的item
        List<OrderItem> orderItems = orderItemMapper.selectByUserIdOrderNoSet(orderNoSet);

        Map<Long, List<OrderItem>> orderItemMap = orderItems.stream()
                .collect(Collectors.groupingBy(OrderItem::getOrderNo));

        //shipping
        Set<Integer> shippingIdSet = orders.stream().map(Order::getShippingId).collect(Collectors.toSet());
        List<Shipping> shippingList = shippingMapper.selectByShippingIdSet(shippingIdSet);
        Map<Integer, Shipping> shippingMap = shippingList.stream().collect(Collectors.toMap(Shipping::getId, shipping -> shipping));

        //组装
        for (Order order : orders
        ) {
            List<OrderItem> orderItems1 = orderItemMap.get(order.getOrderNo());
            OrderVo orderVo = buildOrderVo(order, orderItemMap.get(order.getOrderNo()), shippingMap.get(order.getShippingId()));
            orderVos.add(orderVo);
        }

        PageInfo<OrderVo> pageInfo = new PageInfo<>(orderVos);
        return ResponseVo.success(pageInfo);
    }

    private Long generateOrderNo() {
        return System.currentTimeMillis() + new Random().nextInt(999);
    }

    @Override
    public ResponseVo<OrderVo> detail(Integer uid, Long orderNo) {

        Order order = orderMapper.selectByUserIdOrderNo(uid, orderNo);
        if (order == null) {
            return ResponseVo.error(ResponseEnum.ORDER_NOT_EXIST);
        }
        Shipping shipping = shippingMapper.selectByPrimaryKey(order.getShippingId());
        List<OrderItem> orderItems = orderItemMapper.selectByOrderNo(order.getOrderNo());

        OrderVo orderVo = buildOrderVo(order, orderItems, shipping);

        return ResponseVo.success(orderVo);
    }

    @Override
    public ResponseVo cancelOrder(Integer uid, Long orderNo) {

        Order order = orderMapper.selectByUserIdOrderNo(uid, orderNo);

        if (order == null) {
            return ResponseVo.error(ResponseEnum.PASSWORD_ERROR, "该用户没有此订单");
        }

        if (order.getStatus().equals(OrderStatusEnum.PAID.getCode())) {
            return ResponseVo.error(ResponseEnum.PASSWORD_ERROR, "此订单已付款，无法被取消");
        }
        if (!order.getStatus().equals(OrderStatusEnum.NO_PAY.getCode())){
            return ResponseVo.error(ResponseEnum.ORDER_STATUS_ERROR);
        }

        order.setStatus(OrderStatusEnum.CANCELED.getCode());
        int updateCount = orderMapper.updateByPrimaryKeySelective(order);
        if (updateCount <= 0){
            return ResponseVo.error(ResponseEnum.ERROR);
        }

        return ResponseVo.success();
    }

    @Override
    public void paid(Long orderNo) {
        Order order = orderMapper.selectByOrderNo(orderNo);

        if (order == null){
            throw new RuntimeException(ResponseEnum.ORDER_NOT_EXIST.getDesc() + "订单编号："+orderNo);
        }

        if (!order.getStatus().equals(OrderStatusEnum.NO_PAY.getCode())){
            throw new RuntimeException(ResponseEnum.ORDER_STATUS_ERROR.getDesc() + "订单id："+ orderNo);
        }

        order.setStatus(OrderStatusEnum.PAID.getCode());
        order.setPaymentTime(new Date());
        int row = orderMapper.updateByPrimaryKeySelective(order);
        if (row <= 0){
            throw new RuntimeException("更新订单状态为已支付时失败，订单id："+orderNo);
        }

    }


    private OrderVo buildOrderVo(Order order, List<OrderItem> orderItems, Shipping shipping) {

        List<OrderItemVo> orderItemVos = orderItems.stream().map(this::orderItem2OrderItemVo).collect(Collectors.toList());

        OrderVo orderVo = new OrderVo();
        BeanUtils.copyProperties(order, orderVo);
        orderVo.setOrderItemVoList(orderItemVos);
        orderVo.setShippingVo(shipping);

        return orderVo;
    }

    private Order buildOrder(Long orderNo, Integer uid, List<OrderItem> orderItems, Integer shippingId) {
        Order order = new Order();

        BigDecimal payment = BigDecimal.ZERO;

        for (OrderItem orderItem : orderItems
        ) {
            payment = payment.add(orderItem.getTotalPrice());
        }

        order.setOrderNo(orderNo);
        order.setPayment(payment);
        order.setPaymentType(PaymentTypeEnum.PAY_ONLINE.getCode());
        order.setPostage(0);
        order.setStatus(OrderStatusEnum.NO_PAY.getCode());
        order.setCreateTime(new Date());
        order.setUserId(uid);
        order.setShippingId(shippingId);
        return order;
    }

    private OrderItem buildOrderItem(Integer uid, Long orderNo, Integer quantity, Product product) {
        OrderItem item = new OrderItem();
        item.setUserId(uid);
        item.setOrderNo(orderNo);
        item.setProductId(product.getId());
        item.setProductName(product.getName());
        item.setProductImage(product.getMainImage());
        item.setCurrentUnitPrice(product.getPrice());
        item.setQuantity(quantity);
        item.setTotalPrice(product.getPrice().multiply(BigDecimal.valueOf(quantity)));
        return item;
    }

    private OrderItemVo orderItem2OrderItemVo(OrderItem orderItem) {
        OrderItemVo orderItemVo = new OrderItemVo();
        BeanUtils.copyProperties(orderItem, orderItemVo);
        return orderItemVo;
    }

}
